#ifndef __TEMPLATE_CLASS_H__
#define __TEMPLATE_CLASS_H__

template<class T>
class A {
public:
    T g(T a, T b);
    A();
};

 /*
 非类型模板的形参只能是整型，指针和引用,当为整数时必须是常量
 template<class a, int b> class A {};
 int b;
 A<int, b> m;  is wrong
 const int b;
 A<int, b> m;  is right

 template<double d, class T>  Wrong, double canot support, only support int, *, &
 非类型形参一般不应用于函数模板中
 template<class T, int a> void h(T b) {}
 h(2) is wrong
 h<int, 3>(2) is right

 非类型模板形参的形参和实参间所允许的转换
 1、允许从数组到指针，从函数到指针的转换。如：template <int *a> class A{}; int b[1]; A<b> m;即数组到指针的转换
 2、const修饰符的转换。如：template<const int *a> class A{}; int b; A<&b> m;   即从int *到const int *的转换。
 3、提升转换。如：template<int a> class A{}; const short b=2; A<b> m; 即从short到int 的提升转换
 4、整值转换。如：template<unsigned int a> class A{};   A<3> m; 即从int 到unsigned int的转换。
 5、常规转换。
*/

template<class T, int MAXSIZE>
class Stack {
private:
    T elems[MAXSIZE];
    int numElems;

public:
    Stack();
    void push(T const&);
    void pop();
    T top() const;
    bool empty() const {
        return numElems == 0;
    }
    bool full() const {
        return numElems == MAXSIZE;
    }
};

//非类型形参实例
template<typename T> 
class CompareDemo{
public:
    int compare(const T&, const T&);
};

// 可以为类模板的类型形参提供默认值，但不能为函数模板的类型形参提供默认值。函数模板和类模板都可以为模板的非类型形参提供默认值。
// template<class T1, class T2=int> class A{};
// 类模板类型形参默认值和函数的默认参数一样，如果有多个类型形参则从第一个形参设定了默认值之后的所有模板形参都要设定默认值，比如template<class T1=int, class T2>class A{};就是错误的，因为T1给出了默认值，而T2没有设定
// 在类模板的外部定义类中的成员时template 后的形参表应省略默认的形参类型。比如template<class  T1, class T2=int> class A{public: void h();}; 定义方法为template<class T1,class T2> void A<T1,T2>::h(){}
#endif
